using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Security;
using System.Security.Principal;
using System.Reflection;

namespace SBPweb.Security.Authorization
{
	/// <summary>
	/// Class of MembershipUser
	/// </summary>
	public class MembershipUser: System.Web.Security.MembershipUser, IPrincipal
	{
		#region Private fields

		private IPrincipal principal;
		private IIdentity identity;
		private Dictionary<string, IdentityReference> mAvailableRoles;

		#endregion

		#region Constructor logic

		/// <summary>
		/// Consturctor of Memebrshipuser
		/// </summary>
		public MembershipUser()
		{
			//Initialize(WindowsIdentity.GetCurrent());
			identity = WindowsIdentity.GetCurrent();
			WindowsIdentity wI = identity as WindowsIdentity;
			if (wI != null)
			{
				principal = new WindowsPrincipal(wI);
			}
			else
			{
				principal = new GenericPrincipal(identity, new string[] { });
			}
		}

		/// <summary>
		/// Constructor of MembershipUser
		/// </summary>
		/// <param name="_identity">windows identity</param>
		public MembershipUser(WindowsIdentity _identity)
		{
			Initialize(_identity);
			principal = new WindowsPrincipal(_identity);
		}

		/// <summary>
		/// Constructor of MembershipUser
		/// </summary>
		/// <param name="principal">principal</param>
		public MembershipUser(IPrincipal principal)
		{
			this.principal = principal;
			Initialize(principal.Identity);
		}

		private void Initialize(IIdentity user)
		{
            Assembly asm = Assembly.GetEntryAssembly();
            if (asm == null)
            {
                asm = Assembly.GetExecutingAssembly();
            }
			this.identity = new GenericIdentity(user.Name, asm.GetName().Name);
		}

		#endregion

		#region Public property accessors

		/// <summary>
		/// user identity
		/// </summary>
		public IIdentity Identity
		{
		    get
		    {
		        return identity;
		    }
		}

		/// <summary>
		/// Dictionary of available roles
		/// </summary>
		public Dictionary<string, IdentityReference> AvailableRoles
		{
			get
			{
				if (mAvailableRoles == null)
				{
					Dictionary<string, IdentityReference>  availableRoles;
					string[] retVal;
					Type idType = principal.Identity.GetType();
					if (idType == typeof(WindowsIdentity))
					{
						availableRoles = new Dictionary<string, IdentityReference>();
						IdentityReferenceCollection groupRefs = (principal.Identity as WindowsIdentity).Groups;
						retVal = new string[groupRefs.Count];
						foreach (IdentityReference ir in groupRefs)
						{
							NTAccount account = ir.Translate(typeof(NTAccount)) as NTAccount;
							availableRoles[account.Value.ToUpper()] = ir;
						}
						System.Threading.Interlocked.CompareExchange(ref mAvailableRoles, availableRoles, null);
					}
					else
					{
						//TODO: implement more cases;
					}
				}
				return mAvailableRoles;
			}
		}

		#endregion

		#region IPrincipal Members

		/// <summary>
		/// Is in role?
		/// </summary>
		/// <param name="role">role</param>
		/// <returns>success</returns>
		public bool IsInRole(string role)
		{
			#region Hack

			return true;

			#endregion

			#region Default: FALSE

			//return principal.IsInRole(role);

			#endregion

			#region Previous version
			/*
			foreach (IdentityReference ir in (identity as WindowsIdentity).Groups)
			{
			    if (role == Authorization.SIDHandler.GetName(ir.Value))
			    {
			        return true;
			    }
			}
			*/
			/*
			if ((role.ToLower() == "admin") && (user.Name == "admin"))
			{
			    return true;
			}
			return false;
			*/
			#endregion

			#region New  version

			/*
			if (AvailableRoles != null)
			{
				return AvailableRoles.ContainsKey(role.ToUpper());
			}
			return false;
			*/

			#endregion
		}

		/// <summary>
		/// Is at least one is in role?
		/// </summary>
		/// <param name="roles">roles</param>
		/// <returns>success</returns>
		public bool IsInOneOfTheRoles(IList roles)
		{
			if (roles == null || roles.Count == 0)
			{
				return true;
			}

			List<string> list = new List<string>();

			foreach (object o in roles)
			{
				list.Add(o.ToString());
			}

			return IsInOneOfTheRoles(list);
		}

		/// <summary>
		/// Is at least one is in role?
		/// </summary>
		/// <param name="roles">roles</param>
		/// <returns>success</returns>
		public bool IsInOneOfTheRoles(List<string> roles)
		{
			if (roles == null || roles.Count == 0)
			{
				return true;
			}

			foreach (string role in roles)
			{
				if (IsInRole(role))
				{
					return true;
				}
			}

			return false;
		}

		#endregion

		#region Public methods

		string[] IntersectRoles(string[] roles)
		{
			List<string> retVal;
			if (AvailableRoles != null)
			{
				retVal = new List<string>();
				foreach (string role in roles)
				{
					if (AvailableRoles.ContainsKey(role))
					{
						retVal.Add(role);
					}
				}
				return retVal.ToArray();
			}
			return null;
		}

		#endregion

		#region Overridden methods
		/// <summary>
		/// Change password
		/// </summary>
		/// <param name="oldPassword">old password</param>
		/// <param name="newPassword">new password</param>
		/// <returns>success</returns>
		public override bool ChangePassword(string oldPassword, string newPassword)
		{
			return System.Web.Security.Membership.Provider.ChangePassword(this.identity.Name, oldPassword, newPassword);
		}
		#endregion
	}
}